<script setup lang="ts" name="Header">//setup语法糖
import { ref, reactive, toRefs, toRef, computed, watch, watchEffect, defineExpose, defineProps, withDefaults, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'
import { type PersonInter, type Persons } from '@/types'
let name = ref('zhangsan') //ref响应式(RefImpl对象): 基本类型(数字,字符串), 对象(层级不深)
let cars = ref({ brand: '奔驰', price: 100 }) //ref对象(层级不深)
let car = reactive({ brand: '奔驰', price: 100, person: '个人' }) //reactive相应式(Proxy代理函数): 只能对象数组(层级深)
let { brand, price } = toRefs(car) //toRefs: 将reactive中k-v全转为ref,解构赋值为响应式(ObjectRefImpl)
let brands = toRef(car, 'brand') //toRef: 将reactive中某个k-v转为ref

let compute = computed({ //计算属性(ref响应式)
  get() {
    return name.value + '-' + 'san' //3.返回li-san
  },
  set(val) {
    const [str1, str2] = val.split('-') //2.将li赋值改name
    name.value = str1!
  }
})
function computeds() {
  compute.value = 'li-si' //1.触发计算属性中set方法
}

// const stopWatch = watch(name, (newValue, oldValue) => { //监视ref基本类型,不写.value
//   console.log(newValue, oldValue)
//   if (newValue === 'lisi') {
//     stopWatch() //停止监视
//   }
// })
// watch(cars, (newValue, oldValue) => { //监视ref对象(地址值,或对象属性值)
//   console.log(newValue, oldValue)
// }, { deep: true, immediate: true }) //深度监视,立即监视
// watch(car, (newValue, oldValue) => { //监视reactive对象(默认深度监视,无法关闭)
//   console.log(newValue, oldValue)
// })
// watch(() => car.brand, (newValue, oldValue) => { //监视ref或reactive对象某个基本类型属性(通过getter函数返回值)
//   console.log(newValue, oldValue)
// })
// watch(() => car.person, (newValue, oldValue) => { //监视ref或reactive对象某个对象类型属性(推荐通过getter函数返回值,也可直接写car.person)
//   console.log('')
// }, { deep: true })
watch([() => car.brand, () => car.person], (newValue, oldValue) => { //监视包含上述的数组
  console.log(newValue, oldValue)
}, { deep: true })

watchEffect(() => { //自动监视:不用指定监视谁,用到就监视,立即监视(一上来就监视)
  if (name.value == 'lisi') {
    console.log(name.value)
  }
})

let age = 1
function refs() {
  name.value = 'lisi' //ref: js中必须.value，模板中不用.value
  cars.value.price += 1 //ref: 对象.value
  age += 1 //不是响应式
}
function reactives() {
  car.price += 10 //reactive及其内部ref: 不用.value
  //car = {brand:'宝马', price:100} //reactive:重新分配对象会失去相应式
  Object.assign(car, { brand: '宝马', price: 100 }) //reactive:将后端返回的对象属性加到car
  cars.value = { brand: '宝马', price: 100 } //ref:重新分配对象还是相应式(因为.value必是响应式)
}
function reactiveToRefs() {
  brand.value = '法拉利' //将reactive中k-v全转为ref，修改ref中值,原reactive也会改(因为响应式)
}

let person: PersonInter = { id: '123', name: '王五', age: 18 } //ts:定义属性类型
let personList: Array<PersonInter> = [
  { id: '123', name: '王五', age: 18 },
  { id: '123', name: '赵六', age: 20 }
]
let persons: Persons = [
  { id: '123', name: '王五', age: 18 },
  { id: '123', name: '赵六', age: 20 }
]

console.log('setup即为vue2的创建前,创建后') //生命周期钩子函数
onBeforeMount(() => {
  console.log('挂载前')
})
onMounted(() => {
  console.log('**挂载完')
})
onBeforeUpdate(() => {
  console.log('更新前')
})
onUpdated(() => {
  console.log('**更新完')
})
onBeforeUnmount(() => {
  console.log('**卸载前')
})
onUnmounted(() => {
  console.log('卸载完')
})

import useSum from '@/hooks/useSum' //hooks封装数据和方法
import useDog from '@/hooks/useDog'
const { sum, add, bigSum } = useSum()
const { dogList, getDog } = useDog()
</script>

<template> <!--template不编译-->
  <div class="component-name"> <!--vue3无需根标签-->
    <h5>头部非路由组件</h5>
    <button @click="refs">相应式ref</button>{{ name }}{{ cars }}{{ age }} <br />
    <button @click="reactives">相应式reactive</button>{{ car }} <br />
    <button @click="reactiveToRefs">toRefs和toRef转换</button>{{ brand }}{{ price }}{{ brands }} <br />
    <button @click="computeds">computed计算属性</button>{{ compute }} <br />
    <button @click="getDog">hooks封装数据和方法1</button>{{ dogList }} <br />
    <button @click="add">hooks封装数据和方法2</button>{{ sum }}{{ bigSum }}
  </div>
  <div class="component-name">
  </div>
</template>

<style lang="less" scoped>
//less嵌套写法,scoped域:样式只对当前组件有效
.component-name {
  color: hsl(0, 58%, 46%);
  font-size: 30px;
}
</style>